<?php

namespace App\Controller\System;

use App\Constants\ErrorCode;
use App\Controller\AbstractController;
use App\DataStore\RedisGeneral;
use App\Repository\Contro\FileContro;
use App\Service\Files\FilesService;
use Hyperf\Di\Annotation\Inject;

class FileController extends AbstractController
{
    #[Inject]
    public FilesService $filesService;

    #[Inject]
    public FileContro $fileContro;

    public function upload(){
        $file = $this->request->file('file');
        $fileName = $file->getClientFilename();
        $fileExt = strtolower($file->getExtension());
        $mimeType = strtolower($file->getMimeType());
        $expectedMimeTypes = [
            'image/jpeg',
            'image/png',
            'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // Word
            'application/msword', // Word 97-2003
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // Excel
            'application/vnd.ms-excel', // Excel 97-2003
            'application/zip', // ZIP
            'application/x-zip-compressed', // ZIP
            'application/x-rar-compressed', // RAR
            'application/x-7z-compressed'
        ];

        $expectedExtensions = [
            'jpg',
            'jpeg',
            'png',
            'doc',
            'docx',
            'xls',
            'xlsx',
            'zip',
            '7z',
            'rar',
        ];

        // 获取临时文件路径
        $tempFilePath = $file->getStream()->getMetadata('uri');
        // 计算文件的 MD5 值
        $fileMd5 = md5_file($tempFilePath);
        try {
            // 验证文件的 MIME 类型和扩展名
            if (in_array($mimeType, $expectedMimeTypes) && in_array($fileExt, $expectedExtensions)) {
                // 校验当前文件是否已经被上传过
                $fileIsExits = $this->fileContro->getFileByMd5($fileMd5);
                if($fileIsExits){
                    return success([
                        'id' => $fileIsExits['id'],
                        'real_name' => $fileIsExits['real_name'],
                    ]);
                }
                // 处理文件名 随机文件名
                $saveName = md5($fileName.time()).".".$fileExt;
                $path = date('Y-m-d').DIRECTORY_SEPARATOR.$saveName;
                $savePath = $this->filesService->uploadFile($file,$path);
                $saveData = [
                    'organ_id' => getOrganIdByOrganCode(),
                    'file_md5' => $fileMd5,
                    'real_name' => $fileName,
                    'save_name' => $saveName,
                    'file_path' => $savePath
                ];
                $fileId = $this->fileContro->addFile($saveData);
                $saveData['id'] = $fileId;
                RedisGeneral::getInc()->setFileMd5($fileMd5,$saveData);
                return success([
                    'id' => $fileId,
                    'real_name' => $fileName
                ]);
            } else {
                apiError(ErrorCode::CODE_TYPE_FILE_ERROR_TYPE->getMessage());
            }
        }catch (\Exception $exception){
            apiError(ErrorCode::CODE_TYPE_FILE_ERROR->getMessage());
        }
    }

    public function download(int $fileId){
        $fileInfo = $this->fileContro->getFile($fileId);
        if(empty($fileInfo)){
            apiError(ErrorCode::CODE_TYPE_FILE_ERROR_DOWNLOAD->getMessage());
        }
        if(!$this->filesService->fileExist($fileInfo['file_path'])){
            apiError(ErrorCode::CODE_TYPE_FILE_ERROR_DOWNLOAD->getMessage());
        }
        $response = $this->response
            ->withHeader('Content-Description', 'File Transfer')
            ->withHeader('Content-Type', 'application/octet-stream')
            ->withHeader('Content-Disposition', 'attachment; filename="' . $fileInfo['real_name'] . '"')
            ->withHeader('Expires', '0')
            ->withHeader('Cache-Control', 'must-revalidate')
            ->withHeader('Pragma', 'public');
        // 设置响应体内容
        $content = $this->filesService->getLocalFile($fileInfo['file_path']);
        $response->getBody()->write($content);
        return $response;
    }
}